--------------Wordzzzearch-------------
A 4am crack                  2017-11-22
---------------------------------------

Name: Wordzzzearch
Genre: educational
Year: 1989
Credits: Methods & Solutions
Publisher: Mindplay, Inc.
Platform: Apple ][+ or later
Media: single-sided 5.25-inch floppy
OS: DOS 3.3
Previous cracks: none

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  read error on third pass

Locksmith Fast Disk Backup
  unable to read track $14
  copy boots DOS, shows a title screen,
  then hangs with the drive motor on

EDD 4 bit copy (no sync, no count)
  no errors, but copy boots DOS, shows
  a title screen, then displays
  "DISK ERROR 35W" and hangs

Copy ][+ nibble editor
  track $14 is almost entirely sync
  bytes, with the occasional $D5 nibble
  (almost certainly a protection track)

Disk Fixer
  entire disk is standard except T14
  T00,S00 -> DOS 3.3 bootloader
  T01,S09 -> startup program is "HELLO"
  standard DOS 3.3 disk catalog on T11

Why didn't any of my copies work?
  specially formatted nibble sequence
  on track $14, designed to fool even
  the best bit copiers

Next steps:

  1. Find the protection check that is
     reading track $14
  2. Disable it
  3. Declare victory (*)

(*) go to the gym

                   ~

               Chapter 1
         In Which We Get Lucky


One thing that all protection checks
have in common is they need to access
the disk drive. Since most protection
checks exploit edge cases of how bits
are stored on disk, they need to use
the lowest level access methods to
manipulate those bits manually.

The lowest level way to "read" a disk
is the data latch softswitch address in
the $C0xx range. For slot 6, it's
$C0EC, but to allow disks to boot from
any slot, developers usually use code
like this:

  LDX <slot number x 16>
  LDA $C08C,X

There's nothing that says you have to
use the X-register as the index or the
accumulator as the load register. But
most disks do, out of convention I
suppose (or fear of messing up such
low-level code in subtle ways).

Also, since developers don't actually
want people finding their protection-
related code, they may try to encrypt
it or obfuscate it on disk, in memory,
or both. But eventually, the code must
exist and the code must run, and it
must run on my machine, and I have the
final say on what my machine does or
does not do.

But sometimes you get lucky.

Turning to my trusty Disk Fixer sector
editor, I search the non-working copy
for "BD 8C C0", which is the opcode
sequence for "LDA $C08C,X".

[Disk Fixer]
  ["F"ind]
    ["H"ex]
      ["BD 8C C0"]

                 --v--

------------- DISK SEARCH -------------

$00/$02-$75   $00/$02-$8B   $00/$02-$B4
$00/$02-$E1   $00/$02-$EB   $00/$02-$F6
$00/$03-$2F   $00/$03-$39   $00/$03-$4F
$00/$03-$59   $00/$03-$64   $00/$03-$71
$00/$03-$79   $00/$03-$8B   $00/$03-$95
$00/$06-$A4   $00/$06-$C0   $00/$07-$27
$00/$07-$37   $00/$07-$3C   $0B/$01-$73
$0B/$01-$83   $0B/$01-$9E   $0B/$01-$AF
$0B/$01-$B9   $0B/$01-$C8   $13/$03-$73
$13/$03-$83   $13/$03-$9E   $13/$03-$AF
$13/$03-$B9   $13/$03-$C8

                 --^--

The matches on track $00 are part of
DOS 3.3, i.e. not suspicious. But the
cluster of matches on track $0B and $13
are highly suspect.

                   ~

               Chapter 2
      In Which We Find Ourselves
          In Enemy Territory


The protection routine appears to start
at offset $3E.

                 --v--

T0B,S01
----------- DISASSEMBLY MODE ----------
; get boot slot (x16)
003E:A6 2B          LDX   $2B

; save zero page addresses on stack
0040:A5 FD          LDA   $FD
0042:48             PHA
0043:A5 FE          LDA   $FE
0045:48             PHA

; get RWTS parameter table address
0046:20 E3 03       JSR   $03E3
0049:84 FD          STY   $FD
004B:85 FE          STA   $FE

; track $14 -- the mystery track!
004D:A0 04          LDY   #$04
004F:A9 14          LDA   #$14
0051:91 FD          STA   ($FD),Y

; RWTS command = seek
0053:A0 0C          LDY   #$0C
0055:A9 00          LDA   #$00
0057:91 FD          STA   ($FD),Y

; slow down IIgs (has no effect on
; other machines)
0059:AD 36 C0       LDA   $C036
005C:29 7F          AND   #$7F
005E:8D 36 C0       STA   $C036

; disable last line of RWTS that turns
; off the drive motor
0061:A9 60          LDA   #$60
0063:8D 4D BE       STA   $BE4D

; call the RWTS to execute the seek to
; track $14
0066:20 E3 03       JSR   $03E3
0069:20 D9 03       JSR   $03D9

; restore the RWTS code (but the drive
; motor is still on)
006C:A9 BD          LDA   #$BD
006E:8D 4D BE       STA   $BE4D

; if the seek failed for some reason,
; exit
0071:B0 65          BCS   $00D8

; find $D5 nibble
0073:BD 8C C0       LDA   $C08C,X
0076:10 FB          BPL   $0073
0078:48             PHA
0079:68             PLA
007A:C9 D5          CMP   #$D5
007C:D0 F5          BNE   $0073

; initialize a checksum
007E:A0 00          LDY   #$00
0080:8C 5D 49       STY   $495D

; count number of $F7 nibbles before
; another $D5 nibble
0083:BD 8C C0       LDA   $C08C,X
0086:10 FB          BPL   $0083
0088:C9 D5          CMP   #$D5
008A:F0 0F          BEQ   $009B
008C:C9 F7          CMP   #$F7
008E:D0 01          BNE   $0091
0090:C8             INY

; the sum of the nibbles themselves
; constitutes the checksum
0091:18             CLC
0092:6D 5D 49       ADC   $495D
0095:8D 5D 49       STA   $495D
0098:4C D5 48       JMP   $48D5
009B:98             TYA
009C:F0 E0          BEQ   $007E

; skip $FF nibbles
009E:BD 8C C0       LDA   $C08C,X
00A1:10 FB          BPL   $009E
00A3:48             PHA
00A4:68             PLA
00A5:C9 FF          CMP   #$FF
00A7:F0 F5          BEQ   $009E

; if next nibble is $D5, fail
00A9:C9 D5          CMP   #$D5
00AB:F0 35          BEQ   $00E2

; skip several more nibbles
00AD:A0 05          LDY   #$05
00AF:BD 8C C0       LDA   $C08C,X
00B2:10 FB          BPL   $00AF
00B4:48             PHA
00B5:68             PLA
00B6:88             DEY
00B7:D0 F6          BNE   $00AF

; skip $FF nibbles
00B9:BD 8C C0       LDA   $C08C,X
00BC:10 FB          BPL   $00B9
00BE:48             PHA
00BF:68             PLA
00C0:C9 FF          CMP   #$FF
00C2:F0 F5          BEQ   $00B9

; if next nibble is not $D5, fail
00C4:C9 D5          CMP   #$D5
00C6:D0 1A          BNE   $00E2

; skip $FF nibbles
00C8:BD 8C C0       LDA   $C08C,X
00CB:10 FB          BPL   $00C8
00CD:C9 FF          CMP   #$FF
00CF:D0 11          BNE   $00E2

; verify checksum, branch on failure
00D1:AD 5D 49       LDA   $495D
00D4:C9 10          CMP   #$10
00D6:D0 0A          BNE   $00E2

; success path falls through to here --
; turn off drive motor, restore zero
; page, and return to caller gracefully
00D8:BD 88 C0       LDA   $C088,X
00DB:68             PLA
00DC:85 FE          STA   $FE
00DE:68             PLA
00DF:85 FD          STA   $FD
00E1:60             RTS

; all failures lead here --
; wipe memory
00E2:A2 60          LDX   #$60
00E4:A9 A0          LDA   #$A0
00E6:99 FF 4F       STA   $4FFF,Y
00E9:C8             INY
00EA:D0 FA          BNE   $00E6
00EC:EE 3A 49       INC   $493A
00EF:CA             DEX
00F0:D0 F4          BNE   $00E6
00F2:AD 8A C0       LDA   $C08A

; display encrypted error message
; "DISK ERROR 35W"
00F5:20 2F FB       JSR   $FB2F
00F8:20 58 FC       JSR   $FC58
00FB:A0 0E          LDY   #$0E
00FD:B9 5E 49       LDA   $495E,Y

[continued on T0B,S00]

0000:49 BB          EOR   #$BB
0002:99 B4 05       STA   $05B4,Y
0005:88             DEY
0006:10 F5          BPL   $FFFD
0008:78             SEI

; hang forever
0009:30 FE          BMI   $0009

(This is the behavior I saw on my non-
working EDD bit copy.)

There are no side effects. Replacing
the first byte with an "RTS" will
bypass the entire thing.

T0B,S01,$3E: A6 -> 60

]PR#6
...works...

There is an identical protection check
on T13,S03 which seems to be an unused
sector, but I patched it anyway because
life is short.

T13,S03,$3E: A6 -> 60

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 1540
------------------EOF------------------
